#include "client_fileOp.h"
#include "../head/cmd_parse.h"
/*Usage: 接收文件*/
int recvn(int sockfd,void *buf,ssize_t length){// 解决半包问题
    char *p = (char *)buf;
    ssize_t cursize = 0;
    while(cursize < length){
        ssize_t sret = recv(sockfd,p + cursize,length - cursize,0);
        cursize += sret;
    }
    return 0;
}

int getFileName(const char *Path,char *fileName,int length){// /home/test1/.../client/file1
    char buf[1024] = {0};
    strcpy(buf,Path);
    char delim[2] = "/";
    char *token = strtok(buf,delim);
    while(token != NULL){
        memset(fileName,0,length);
        strcpy(fileName,token);
        token = strtok(NULL,delim);
        if(token == NULL){
            break;
        }
    }
    return 0;
}

int getsFile(int sockfd,const char *abPath,const char *cloudPath){// 本地绝对路径 云端虚拟路径
    printf("join gets!\n");
    train_t train;
    struct stat statbuf;
    int fd;
    off_t cursize = 0;
    off_t filesize;
    char path[1024];
    bzero(path,sizeof(path));
    char buf[1024];
    bzero(buf,sizeof(buf));
    char clPath[1024];
    bzero(clPath,sizeof(clPath));
    getFileName(cloudPath,clPath,sizeof(clPath));
    printf("abPath:%s\n",path);
    strcpy(path,abPath);
    printf("path:%s\n",path);
    strcat(path,clPath);
    printf("path:%s\n",path);
    int ret = access(path,F_OK);// 判断文件是否存在
    if(ret == 0){
        printf("Redownload!\n");
        fd = open(path,O_RDWR);
        fstat(fd,&statbuf);
        cursize = statbuf.st_size;// 获取已传输了多少
    }else if(ret == -1){
        fd = open(path,O_RDWR|O_CREAT|O_TRUNC,0666);// 没有就建一个新的
    }else{
        return -1;
    }
    printf("cursize:%ld\n",cursize);
    send(sockfd,&cursize,sizeof(cursize),0);// 告诉客户端已经传了多少
    printf("send the cursize to server!\n");
    printf("%d\n",train.cmd);
    printf("%ld\n",sizeof(train.cmd));
    recvn(sockfd,&train.cmd,sizeof(train.cmd));
    printf("1,%d\n",train.cmd);
    recvn(sockfd,&train.length,sizeof(train.length));
    printf("2,%d\n",train.length);
    recvn(sockfd,train.data,train.length);// 接收文件实际大小内容
    printf("3\n");
    memcpy(&filesize,train.data,train.length);
    printf("filesize = %ld\n",filesize);
    // 开始传输
    ftruncate(fd,cursize+filesize);
    char *p = (char *)mmap(NULL,cursize+filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    recvn(sockfd,p+cursize,filesize);
    // 传输完成
    recv(sockfd,buf,sizeof(buf),0);
    printf("%s\n",buf);
    close(fd);
    return 0;
}

int putsFile(int sockfd,const char *abPath){
    train_t train;
    train.cmd = -1;// 没用
    off_t cursize;
    char path[1024];
    bzero(path,sizeof(path));
    char buf[1024];// 
    bzero(buf,sizeof(buf));
    strcpy(path,abPath);
    printf("file:%s\n",path);
    int fd = open(path,O_RDWR);//绝对路径打开文件
    struct stat statbuf;
    fstat(fd,&statbuf);
    printf("%ld\n",statbuf.st_size);

    recvn(sockfd,&train.cmd,sizeof(train.cmd));
    printf("train.cmd%d\n",train.cmd);
    recvn(sockfd,&train.length,sizeof(train.length));
    recvn(sockfd,&train.data,train.length);
    memcpy(&cursize,train.data,train.length);// 收到当前已上传多少
    printf("after recv\n");
    if(cursize > 0){
        printf("Reupload!\n");
    }
    printf("filesize = %ld\n",statbuf.st_size - cursize);
    off_t filesize = statbuf.st_size - cursize;// 文件实际传输大小
    train.length = sizeof(filesize);
    memcpy(train.data,&filesize,sizeof(off_t));
    send(sockfd,&train,sizeof(train.cmd)+sizeof(train.length)+train.length,MSG_NOSIGNAL);
    if(filesize > 100000000){
        ftruncate(fd,filesize);
        char *p =(char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        send(sockfd,p+cursize,filesize,MSG_NOSIGNAL);
        munmap(p,filesize);
    }else{
        off_t curSize = cursize;
        sendfile(sockfd,fd,&curSize,filesize);// 从cursize继续传输
    }
    // 上传完成
    recv(sockfd,buf,sizeof(buf),0);
    printf("%s\n",buf);
    close(fd);
    return 0;
}
